from petiteappli.xenocide.world import World

import math

import os
import logging

import ogre.renderer.OGRE as ogre
import ogre.io.OIS as OIS
import ogre.gui.CEGUI as CEGUI






class Singleton(type):
    def __init__(cls,name,bases,dic):
        super(Singleton,cls).__init__(name,bases,dic)
        cls.instance=None
    def __call__(cls,*args,**kw):
        if cls.instance is None:
            cls.instance=super(Singleton,cls).__call__(*args,**kw)
        return cls.instance

class GameState(object):
    def __init__(self):
        pass
    def enter(self):
        pass
    def exit(self):
        pass
    def pause(self):
        pass
    def resume(self):
        pass
    def keyPressed(self, evt):
        pass
    def keyReleased(self, evt):
        pass
    def windowResized(self, renderWindow,mouseState):
        
        mouseState.width = renderWindow.getViewport(0).getActualWidth()
        mouseState.height = renderWindow.getViewport(0).getActualHeight()

 
    def windowClosed(self, renderWindow):
        # Only close for window that created OIS
        if(renderWindow == self.renderWindow):
            del self
 
### Mouse Listener callbacks ###
 
    def mouseMoved(self, evt):
        # Pass the location of the mouse pointer over to CEGUI
        CEGUI.System.getSingleton().injectMouseMove(evt.get_state().X.rel, evt.get_state().Y.rel)
        
        return True
 
    def mousePressed(self, evt, id):
        # Handle any CEGUI mouseButton events
        
        CEGUI.System.getSingleton().injectMouseButtonDown(self.convertButton(id))
        return self.manager.doMouseDown(evt,id,self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Shift),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Ctrl),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Alt))
        
        
    def mouseReleased(self, evt, id):
        # Handle any CEGUI mouseButton events
        CEGUI.System.getSingleton().injectMouseButtonUp(self.convertButton(id))
        return self.manager.doMouseUp(evt,id,self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Shift),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Ctrl),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Alt))
        
 
 
    def convertButton(self,oisID):
        if oisID == OIS.MB_Left:
            return CEGUI.LeftButton
        elif oisID == OIS.MB_Right:
            return CEGUI.RightButton
        elif oisID == OIS.MB_Middle:
            return CEGUI.MiddleButton
        else:
            return CEGUI.LeftButton     
 
 
    def frameStarted(self, evt):
        return True
    def frameEnded(self, evt):
        return True
    def changeState(self):
        pass
    def pushState(self):
        pass
    def popState(self):
        pass

class InputManager(OIS.KeyListener):
    def __init__(self, manager, rwindow):
        OIS.KeyListener.__init__(self)
        windowHandle = rwindow.getCustomAttributeInt("WINDOW")
        paramList = [("WINDOW", str(windowHandle))]
        inputManager = OIS.createPythonInputSystem(paramList)
        
        self.keyboard = inputManager \
        .createInputObjectKeyboard(OIS.OISKeyboard, True)
        
        self.mouse = self.inputManager\
        .createInputObjectMouse(OIS.OISMouse, True)
        
        self.mouse.setEventCallback(self)
        self.keyboard.setEventCallback(self)

        self.manager = manager
        
        # Listen for any events directed to the window manager's close button
        ogre.WindowEventUtilities.addWindowEventListener(self.renderWindow, self)
       
        self.windowResized(self.renderWindow) 

    def __del__ (self ):
        # Clean up OIS 
        print "QUITING"
        self.delInputObjects()
 
        OIS.InputManager.destroyInputSystem(self.inputManager)
        self.inputManager = None
 
        ogre.WindowEventUtilities.removeWindowEventListener(self.renderWindow, self)
        self.windowClosed(self.renderWindow)
 
    def delInputObjects(self):
        # Clean up the initialized input objects
        if self.keyboard:
            self.inputManager.destroyInputObjectKeyboard(self.keyboard)
        if self.mouse:
            self.inputManager.destroyInputObjectMouse(self.mouse)
        if self.joy:
            self.inputManager.destroyInputObjectJoy(self.mouse)
        
    def keyPressed(self, evt):
        self.manager.keyPressed(evt)
        
    def keyReleased(self, evt):
        self.manager.keyReleased(evt)
        
 
    def windowResized(self, renderWindow):
        self.manager.windowResized(renderWindow)
        mouseState = self.mouse.getMouseState()
        mouseState.width = renderWindow.getViewport(0).getActualWidth()
        mouseState.height = renderWindow.getViewport(0).getActualHeight()

 
    def windowClosed(self, renderWindow):
        # Only close for window that created OIS
        if(renderWindow == self.renderWindow):
            del self
 
### Mouse Listener callbacks ###
 
    def mouseMoved(self, evt):
        # Pass the location of the mouse pointer over to CEGUI
        CEGUI.System.getSingleton().injectMouseMove(evt.get_state().X.rel, evt.get_state().Y.rel)
        
        return True
 
    def mousePressed(self, evt, id):
        # Handle any CEGUI mouseButton events
        
        CEGUI.System.getSingleton().injectMouseButtonDown(self.convertButton(id))
        return self.manager.doMouseDown(evt,id,self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Shift),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Ctrl),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Alt))
        
        
    def mouseReleased(self, evt, id):
        # Handle any CEGUI mouseButton events
        CEGUI.System.getSingleton().injectMouseButtonUp(self.convertButton(id))
        return self.manager.doMouseUp(evt,id,self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Shift),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Ctrl),\
                                        self.keyboard.isModifierDown(OIS.Keyboard.Modifier.Alt))
        
 
 
    def convertButton(self,oisID):
        if oisID == OIS.MB_Left:
            return CEGUI.LeftButton
        elif oisID == OIS.MB_Right:
            return CEGUI.RightButton
        elif oisID == OIS.MB_Middle:
            return CEGUI.MiddleButton
        else:
            return CEGUI.LeftButton     
 
        
        
class GameFrameListener(ogre.FrameListener):
    def __init__(self, gameManager):
        ogre.FrameListener.__init__(self)
        self.gameManager = gameManager
    def frameStarted(self, evt):
        successfulFrame = self.gameManager.frameStarted(evt)
        return successfulFrame
    def frameEnded(self, evt):
        successfulFrame = self.gameManager.frameEnded(evt)
        return successfulFrame
    
class GameManager(object):
    __metaclass__ = Singleton
    def __init__(self):
        self.root = 0
        self.inputManager = 0
        self.states = []
        
        
    def start(self, state):
        self.root = ogre.Root()
        self.defineResources()
        self.setupRenderSystem()
        self.frameListener = GameFrameListener(self)
        self.root.addFrameListener(self.frameListener)
        self.inputManager = InputManager(self, self.RenderWindow)
        self.changeState(state())
        self.root.startRendering()
        
    def changeState(self, state):
        if len(self.states):
            oldState = self.states.pop()
            oldState.exit()
        self.states.append(state)
        state.enter()
        
    def pushState(self, state):
        if len(self.states):
            self.states[-1].pause()
        self.states.append(state)
        state.enter()
        
    def popState(self):
        if len(self.states):
            oldState = self.states.pop()
            oldState.exit()
        if len(self.states):
            self.states[-1].resume()
            
            
    def keyPressed(self, evt):
        self.states[-1].keyPressed(evt)
        
    def keyReleased(self, evt):
        self.states[-1].keyReleased(evt)
        
    def frameStarted(self, evt):
        self.inputManager.keyboard.capture()
        sf = self.states[-1].frameStarted(evt)
        return sf

    def frameEnded(self, evt):
        sf = self.states[-1].frameEnded(evt)
        return sf
    
        